/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package TestPrincipal;

import analisis.InterproceduralCFGAnalysis;
import java.util.HashSet;
import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import reticulado.AbstractNode;
import reticulado.PointsToGraph;
import soot.Body;
import soot.Local;
import soot.PhaseOptions;
import soot.options.Options;
import static org.junit.Assert.*;

/**
 *
 * @author Santiago Avendaño
 */
public class TestEj3 {

    private static final String campoF1 = "f1";
    private static final String campoF2 = "f2";
    private static Local variablex;
    private static Local variabley;
    private static Local variablez;
    private static Local variablea;
    private static Local variablec;
    private static Local variabled;

    public TestEj3() {
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }

    @Before
    public void setUp() {
    }

    @After
    public void tearDown() {
    }

    @Test
    public void TestPrincipal() {
        Options.v().set_keep_line_number(true);
        // Mantener los nombres de las variables tal cual estan en el codigo
        PhaseOptions.v().setPhaseOption("jb", "use-original-names:true");
        //esto es para que soot encuentre la clase java.lang.Object en Mac OS
        //Options.v().set_soot_classpath(System.getProperty("java.class.path") + System.getProperty("path.separator") + System.getProperty("sun.boot.class.path"));

        PointsToGraph out;

        System.out.println("Corriendo Tests Inter 3");

        System.out.println("Corriendo Test_1");

        InterproceduralCFGAnalysis inter = new InterproceduralCFGAnalysis("tests.inter.Test1", "test_1");
        setearVariables(inter.getMetodoPrincipal().getActiveBody());
        out = inter.getResult();
        System.out.println(out.toString());
        assertFalse("z.f1 may-alias z.f2 ? NO", out.mayAlias(variablez, campoF1, variablez, campoF2));
        assertTrue("z.f2 may-alias z ? SI", out.mayAlias(variablez, campoF2, variablez));
        System.out.println("Fin Test_1 \n");

        System.out.println("Corriendo Test_2");
        inter = new InterproceduralCFGAnalysis("tests.inter.Test2", "test_02");
        setearVariables(inter.getMetodoPrincipal().getActiveBody());
        out = inter.getResult();
        assertTrue("z.f2 may-alias z.f1 ? SI", out.mayAlias(variablez, campoF2, variablez, campoF1));
        assertFalse("z.f2 may-alias z ? NO", out.mayAlias(variablez, campoF2, variablez));
        System.out.println("Fin Test_2\n");

        System.out.println("Corriendo Test_3");
        inter = new InterproceduralCFGAnalysis("tests.inter.Test3", "test_03");
        setearVariables(inter.getMetodoPrincipal().getActiveBody());
        out = inter.getResult();
        Set<AbstractNode> alcanzadoszf1 = out.alcanzados(variablez, campoF1);
        Set<AbstractNode> alcanzadoszf1f1 = new HashSet<AbstractNode>();
        Set<AbstractNode> alcanzadoszf1f2 = new HashSet<AbstractNode>();
        for (AbstractNode nodo : alcanzadoszf1) {
            alcanzadoszf1f1.addAll(out.alcanzados(nodo, campoF1));
            alcanzadoszf1f2.addAll(out.alcanzados(nodo, campoF2));
        }
        assertTrue("z.f1.f1 maybe null ? NO", out.analizarNulidad(alcanzadoszf1f1) == PointsToGraph.RespuestaNulidad.NO_ES_NULL);
        System.out.println("Fin Test_3");
        System.out.println("");

        System.out.println("Corriendo Test_4");
        inter = new InterproceduralCFGAnalysis("tests.inter.Test4", "test_04");
        setearVariables(inter.getMetodoPrincipal().getActiveBody());
        out = inter.getResult();
        assertTrue("z.f1 may-alias z ? SI", out.mayAlias(variablez, campoF1, variablez));
        assertFalse("z.f2 may-alias z ? NO", out.mayAlias(variablez, campoF2, variablez));
        System.out.println("Fin Test_4");
        System.out.println("");

        System.out.println("Corriendo Test_5");
        inter = new InterproceduralCFGAnalysis("tests.inter.Test5", "test_05");
        setearVariables(inter.getMetodoPrincipal().getActiveBody());
        out = inter.getResult();
        assertTrue("a may-alias c --> SÍ para ej3, NO para ej4", out.mayAlias(variablea, variablec));
        assertTrue("a may-alias d --> SÍ para ej3 y ej4", out.mayAlias(variablea, variabled));
        System.out.println("Fin Test_5");
        System.out.println("");
    }

    private void setearVariables(Body b) {
        String nombreMetodo = b.getMethod().getName();
        for (Local v : b.getLocals()) {
            if (v.getName().equals(nombreMetodo + "_x")) {
                variablex = v;
            }
            if (v.getName().equals(nombreMetodo + "_y")) {
                variabley = v;
            }
            if (v.getName().equals(nombreMetodo + "_z")) {
                variablez = v;
            }
            if (v.getName().equals(nombreMetodo + "_a")) {
                variablea = v;
            }
            if (v.getName().equals(nombreMetodo + "_c")) {
                variablec = v;
            }
            if (v.getName().equals(nombreMetodo + "_d")) {
                variabled = v;
            }
        }
    }
}
